package core;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;

public class Floor implements Serializable {
	private static final long serialVersionUID = -2524877175083650036L;

	public Room[] rooms;
	public Door[] doors;

	public Floor() {
		this.doors = new Door[4];

		this.rooms = new Room[4];
		
		this.generateObject();
	}

	public void generateObject() {
		List<Integer> tmp = new ArrayList<Integer>();
		Random random = new Random();
		int next = -1;
		for (int i = 0; i < 4; i++) {
			do {
				next = Math.abs(random.nextInt()) % 4;
			} while (tmp.contains(next));
			tmp.add(next);
			switch (next) {
			case 0:
				this.rooms[i] = new Room(Room.Type.bedroom);
				break;
			case 1:
				this.rooms[i] = new Room(Room.Type.hall);
				break;
			case 2:
				this.rooms[i] = new Room(Room.Type.kitchen);
				break;
			case 3:
				this.rooms[i] = new Room(Room.Type.living);
				break;
			default:
				break;
			}
			next = Math.abs(random.nextInt()) % 8;
			this.doors[i] = new Door(i, next);
		}
	}

	public void load(Floor floor) {
		this.rooms = floor.rooms;
	}

	public Square.Type get(int i, int j) {
		if (i < 0 || j < 0 || i >= 4 || j >= 8)
			return Square.Type.unknown;
		return this.rooms[i].squares[j].type;
	}
	
	public int get(String roomType) {
		for(int i = 0; i < this.rooms.length; i++)
			if(this.rooms[i].equals(roomType))
				return i;
		return -1;
	}

	public void set(int i, int j, Square.Type st) {
		if (i < 0 || j < 0 || i >= 4 || j >= 8)
			return;
		this.rooms[i].squares[j].type = st;
	}

	public boolean isDoor(int row, int column) {
		if (this.doors[row].row == row && this.doors[row].col == column)
			return true;
		if (row == 0)
			return false;
		if (this.doors[row - 1].row == row && this.doors[row - 1].col == column)
			return true;
		return false;
	}
	
	public void dynamic1() {
		Random random = new Random();
		int position = -1;
		Square.Type type = getNewObject();
		for (int i = 0; i < this.rooms.length; i++) {
			for (int j = 0; j < 8; j++) {
				if (this.rooms[i].squares[j].type == type) {
					this.rooms[i].squares[j].type = Square.Type.clean;
					do {
						position = Math.abs(random.nextInt()) % 8;
					} while(position == j);
					this.rooms[i].squares[position].type = type;
					return;
				}
			}
		}
	}
	
	private Square.Type getNewObject() {
		Random random = new Random();
		int tmp = Math.abs(random.nextInt() % 4);
		switch (tmp) {
		case 0:	
			return Square.Type.flowers;
		case 1:
			return Square.Type.meal;
		case 2:
			return Square.Type.smoking;
		case 3:
			return Square.Type.table;
		default:
			break;
		}
		return Square.Type.clean;
	}
	
	public void dynamic2() {
		Random random = new Random();
		int tmp = -1;
		for(int i = 0; i < this.rooms.length; i++) {
			for(int j = 0; j < 8; j++) {
				if(this.rooms[i].squares[j].type != Square.Type.clean) {
					Square.Type s = this.rooms[i].squares[j].type;
					this.rooms[i].squares[j].type = Square.Type.clean;
					do {
						tmp = Math.abs(random.nextInt() % 8);
					} while(tmp == j);
					this.rooms[i].squares[tmp].type = s;
				}
			}
		}
	}
	
	public void dynamic3() {
		Random random = new Random();
		int tmp = -1;
		Square.Type newObject = null;
		// Per ogni stanza
		for (int i = 0; i < this.rooms.length; i++) {
			//Cerco l'oggetto 
			for (int j = 0; j < 8; j++) {
				if (this.rooms[i].squares[j].type != Square.Type.clean) {
					this.rooms[i].squares[j].type = Square.Type.clean;
					// Scelgo il nuovo oggetto
					do {
						newObject = getNewObject();
					} while (!containsRoom(i, newObject));
					// Scelgo la nuova posizione dell'oggetto
					do {
						tmp = Math.abs(random.nextInt()) % 8;
					} while (tmp == j);
					this.rooms[i].squares[tmp].type = newObject;
					break;
				}
			}
		}
	}
	
	private boolean containsRoom(int n, Square.Type newObject) {
		// Le stanze precedenti non devono contenere l'oggetto newObject.
		for (int i = 0; i < n; i++) { 
			for (int j = 0; j < 8; j++) {
				if (this.rooms[i].squares[j].type == newObject)
					return false;
			}
		}
		return true;
	}
}